module uart_tx_driver(
    input       clk, 
    input       rst_n,
    //uart interface
    output reg  uart_tx,
    //user interface
    input [1:0] bps_select,
    input [7:0] uart_data,
    input       data_en,
    output reg  uart_tx_end
);
//parameter define
parameter BPS_4800   = 14'd10417,
          BPS_9600   = 14'd5208,
          BPS_115200 = 14'd434;
reg  [13:0] cnt_bps_clk;
reg  [13:0] bps;
reg         bps_clk_en;
reg  [3:0]  bps_cnt;
wire [13:0] BPS_CLK_V;
assign BPS_CLK_V = bps >> 1;
//bps_select
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        bps <= 1'd0;
    end
    else begin
        case (bps_select)
            2'd0:bps <= BPS_115200;
            2'd1:bps <= BPS_9600; 
            default:bps <= BPS_4800;
        endcase
    end
end
//cnt_bps_clk
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt_bps_clk <= 'd0;
    end
    else if (cnt_bps_clk >= bps-1 && !data_en) begin
        cnt_bps_clk <= 'd0;
    end
    else begin
        cnt_bps_clk <= cnt_bps_clk + 1'b1;
    end
end
//bps_clk_en
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        bps_clk_en <= 1'b0;
    end
    else if (cnt_bps_clk == BPS_CLK_V-1) begin
        bps_clk_en <= 1'b1;
    end
    else begin
        bps_clk_en <= 1'b0;
    end
end
//bps_cnt
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        bps_cnt <= 'd0;
    end
    else if (bps_cnt == 11) begin
        bps_cnt <= 'd0;
    end
    else if (bps_clk_en) begin
        bps_cnt <= bps_cnt + 1;
    end
end
//uart_tx_end
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        uart_tx_end <= 1'b0;
    end
    else if (bps_cnt == 11) begin
        uart_tx_end <= 1'd1;
    end
    else begin
        uart_tx_end <= 1'b0;
    end
end
//uart_tx
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        uart_tx <= 'd1;
    end
    else case (bps_cnt)
        4'd0: uart_tx <= 1'b1;
        4'd1: uart_tx <= 1'b0;//begin
        4'd2: uart_tx <= uart_data[0];//data
        4'd3: uart_tx <= uart_data[1]; 
        4'd4: uart_tx <= uart_data[2]; 
        4'd5: uart_tx <= uart_data[3]; 
        4'd6: uart_tx <= uart_data[4]; 
        4'd7: uart_tx <= uart_data[5]; 
        4'd8: uart_tx <= uart_data[6]; 
        4'd9: uart_tx <= uart_data[7]; 
        4'd10:uart_tx <= 1'b1; //stop
        default:uart_tx <= 1;
    endcase
end

endmodule //uart_tx_driver